/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_httpd.htm
 *
 * Zhiqim Httpd is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.httpd.context.returns;

import java.util.Map.Entry;

import org.zhiqim.httpd.HttpRequest;
import org.zhiqim.httpd.HttpResponse;
import org.zhiqim.httpd.HttpSession;
import org.zhiqim.httpd.context.ZmlConfig;
import org.zhiqim.httpd.context.core.Context;
import org.zhiqim.httpd.context.core.Return;
import org.zhiqim.kernel.model.maps.HashMapSO;
import org.zhiqim.kernel.model.maps.MapSO;
import org.zhiqim.kernel.model.maps.MapSS;
import org.zhiqim.kernel.util.Htmls;
import org.zhiqim.kernel.util.Lists;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.zml.Zml;
import org.zhiqim.zml.ZmlEngine;
import org.zhiqim.zml.Zmls;

/**
 * 响应处理视图
 *
 * @version v1.0.0 @author zouzhigang 2017-8-21 新建与整理
 */
public class ReturnView implements Return
{
    @Override
    public void process(HttpRequest request)
    {
        process(request, request.getView(), request.getInclude());
    }
    
    public void process(HttpRequest request, String viewPath, String includePath)
    {
        HttpResponse response = request.getResponse();
        HttpSession session = request.getSession();
        
        Context context = (Context)request.getContext();
        ZmlConfig config = context.getConfig();
        ZmlEngine engine = context.getZmlEngine();
        
        //1.页面环境变量表，包括请求中参数和属性
        MapSO variableMap = new HashMapSO();
        
        //1.1先放参数，注意来自参数的数据由外部决定，这里要对其安全过滤
        MapSS paramMap = request.getParameterMap();
        if (!paramMap.isEmpty())
        {
            for (Entry<String, String> entry : paramMap.entrySet())
            {
                String key = entry.getKey();
                String value = Htmls.filterAll(entry.getValue());
                variableMap.put(key, value);
            }
        }

        //1.2再放属性，这里的数据来自Action本身，明确，不作过滤，和参数名相同时覆盖
        variableMap.putAll(request.getAttributeMap());
        
        //1.3 放置Session对应的三个数据
        if (session != null)
        {
            variableMap.put("sessionId", request.getSessionId());
            variableMap.put("sessionUser", request.getSessionUser());
            variableMap.put("sessionName", request.getSessionName());
        }
        
        //1.4 放置范围域
        variableMap.put("request", request);
        variableMap.put("response", response);
        variableMap.put("session", session);
        variableMap.put("context", context);
        variableMap.put("log", log);
        
        try
        {
            //2.放置嵌套包含定义
            if (!Validates.isEmptyBlank(includePath))
            {
                if (includePath.contains("${") || includePath.contains("<#"))
                {//嵌套视图地址包含变量
                    includePath = Zmls.parse(includePath, variableMap, config);
                }
                
                if (!Validates.isEmptyBlank(includePath))
                {
                    variableMap.put("include", includePath);
                    variableMap.put("includeList", Lists.toStringList(includePath));
                }
            }
            
            //视图地址检查
            if (viewPath.contains("${") || viewPath.contains("<#"))
            {//视图地址包含变量
                viewPath = Zmls.parse(viewPath, variableMap, config);
            }
            
            //处理视图
            Zml zml = engine.getZml(viewPath);
            zml.process(response.getOutputStream(), response.getCharacterEncoding(), variableMap, config);
        }
        catch (Exception e) 
        {
            log.error(e);
            try{response.print(e.getMessage() != null?e.getMessage():e.getClass().getName());response.commit();}catch (Throwable e1){}
        }
    }
}
